package com.lagou.niancheng.mvc.dispatcher.core;

import com.lagou.niancheng.mvc.dispatcher.annotations.MyAutowired;
import com.lagou.niancheng.mvc.dispatcher.entity.ScannedClassMetaData;
import com.lagou.niancheng.mvc.dispatcher.exceptions.MyMvcException;

import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * bean的注册中心，包含了所有的bean
 *
 * @description: default
 * @author: 阿秋@niancheng
 * @date: 2020/4/8
 */
public class MyMvcBeanRegistry {


    private Map<String, Object> beanMap;


    public MyMvcBeanRegistry() {
        beanMap = new HashMap<>();
    }

    /**
     * 注册所有的bean
     *
     * @param scannedClassMetaDataList 所有被扫描过的类信息
     */
    public void registryBean(List<ScannedClassMetaData> scannedClassMetaDataList) {
        // 1.实例化所有的bean
        instanceAllBean(scannedClassMetaDataList);
        // 2.依赖注入
        injectionDependencies(scannedClassMetaDataList);
    }

    private void instanceAllBean(List<ScannedClassMetaData> scannedClassMetaDataList) {
        scannedClassMetaDataList.forEach(scannedClassMetaData -> {
            Class beanType = scannedClassMetaData.getBeanType();
            String beanName = scannedClassMetaData.getBeanName();
            try {
                Object o = beanType.newInstance();
                beanMap.put(beanName, o);
            } catch (Exception e) {
                throw new MyMvcException(MessageFormat.format("instant bean({0}) failed", beanName), e);
            }
        });
    }

    private void injectionDependencies(List<ScannedClassMetaData> scannedClassMetaDataList) {
        scannedClassMetaDataList.forEach(scannedClassMetaData -> {
            String beanName = scannedClassMetaData.getBeanName();
            Class beanType = scannedClassMetaData.getBeanType();
            Object bean = beanMap.get(beanName);
            // 获取所有的属性
            Field[] declaredFields = beanType.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                // 判断属性上是否有
                MyAutowired autowired = declaredField.getAnnotation(MyAutowired.class);
                if (autowired == null) {
                    continue;
                }
                // 获取依赖名称
                String dependenceName = declaredField.getName();
                String value = autowired.value();
                if (!value.isEmpty()) {
                    dependenceName = value;
                }
                // 获取依赖bean
                Object dependency = beanMap.get(dependenceName);
                declaredField.setAccessible(true);
                try {
                    declaredField.set(bean, dependency);
                } catch (IllegalAccessException e) {
                    throw new MyMvcException("set property failed", e);
                }
            }
        });
    }


    /**
     * 获取bean
     *
     * @param name bean名称
     * @return
     */
    public Object getBean(String name) {
        return beanMap.get(name);
    }

}
